﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using O2DESNet;
using ShkSimulation.core.dao.statistic;
using ShkSimulation.core.template;
using ShkSimulation.core.util;
using ShkSimulation.desktop.component.tools;
using ShkSimulation.carsharing.impl;

namespace ShkSimulation.desktop.component {

    
    public sealed partial class StatisticConfigControl : UserControl, ResetSimulation {

        private SimulationApplication application;
        private Network Network { get; set; }
        private NetworkResultHolder ResultHolder { get; set; }
        private NetworkEnvironment NetworkInputData { get; set; }
        private ToolTip ToolTip { get; set; }
        private DataReporterBindingList DataReporterBindingList { get; set; }

        #region ReporterGroup

        private IReadOnlyDictionary<string, DataReporter> CurrentShowingReporters => currentShowingReporters;
        private IReadOnlyDictionary<string, DataReporter> currentShowingReporters = new Dictionary<string, DataReporter>();
        
        private IReadOnlyDictionary<string, IReadOnlyList<DataReporter>> ReporterGroup =>
            reporterGroup.AsReadOnly();
        private Dictionary<string, List<DataReporter>> reporterGroup = new Dictionary<string, List<DataReporter>>();
        private BindingList<string> reporterGroupNames = new BindingList<string>();
        #endregion

        #region ReporterCollectionCreated
        private IReadOnlyDictionary<string, DataReporterCollection> DataReporterCollections =>
            dataReporterCollections.AsReadOnly();
        private Dictionary<string, DataReporterCollection> dataReporterCollections = new Dictionary<string, DataReporterCollection>();
        private BindingList<string> dataReporterCollectionNames = new BindingList<string>();
        
        private DataReporterPropertyBindingList singleReporterVariableNames = new DataReporterPropertyBindingList();
        #endregion
		        
        public StatisticConfigControl() {
            InitializeComponent();
            this.Dock = DockStyle.Fill;
            
            CreatedReporterCollectionListBox.DataSource = dataReporterCollectionNames;
            VariableCollectionList.DataSource = singleReporterVariableNames;
            ReporterGroupComboBox.DataSource = reporterGroupNames;
        }
        
        public void SetSimulationApplication(SimulationApplication app) {
            Reset();
            this.application = app;
            this.Name = application.SimulationName;
            application.AfterInitSuccess += this.AfterInitSuccess;
        }
        
        public void Reset() {
            application = null;
            Network = null;
            ResultHolder = null;
            NetworkInputData = null;
            currentShowingReporters = new Dictionary<string, DataReporter>();
            dataReporterCollections.Clear();
            dataReporterCollectionNames.Clear();
            singleReporterVariableNames.Clear();
            reporterGroupNames.Clear();
            reporterGroup.Clear();
            DataReporterBindingList?.Clear();
        }

        private void AfterInitSuccess(SimulationInfo simulationInfo) {
            this.Network = application.SimulationNetwork;
            this.NetworkInputData = application.NetworkInputData;
            this.ResultHolder = application.ResultHolder;

            reporterGroup = Network.ResultCollector.AllDataReporters;
            foreach (var key in reporterGroup.Keys) {
                this.reporterGroupNames.Add(key);
            }
            if (reporterGroup.Count > 0) {
                var first = reporterGroup.First();
                DataReporterBindingList = new DataReporterBindingList(first.Key, first.Value, ReporterSelectView);
            }
            
            var reporters = application.ResultHolder.ReporterCollections;
            foreach (var (key, collection) in reporters) {
                string info = CollectionUtil.StringLimitJoin(collection.Select(each => each.Uniquekey).ToList(), 50);
                Console.WriteLine($@"加载默认DataReporterCollections:{key}，共有{collection.Count}个成员：[{info}]");
                dataReporterCollections.Add(collection.Uniquekey, collection);
                dataReporterCollectionNames.Add(collection.Uniquekey);
            }
            singleReporterVariableNames.Bind(dataReporterCollections[dataReporterCollectionNames.First()]);
            CreatedReporterCollectionListBox.SelectedIndex = 0;
            Refresh();
        }

        private void CreateDataReportersButton_Click(object sender, EventArgs e) {
            if (DataReporterBindingList == null) {
                Console.WriteLine($@"数据采集集合创建失败，没有已加载DataReporter");
                return;
            }
            List<DataReporter> selected = new List<DataReporter>();
            foreach (var agencyDisplay in DataReporterBindingList) {
                if (agencyDisplay.Selected) {
                    selected.Add(CurrentShowingReporters[agencyDisplay.UniqueKey]);
                }
            }
            if (selected.Count == 0) {
                MessageBox.Show($@"请至少选择一个", @"提示");
                return;
            }
            string uniqueKey = SingleTextInputForm.GetInput("输入框", "请输入数据集合唯一键:");
            if (string.IsNullOrEmpty(uniqueKey)) {
                return;
            }
            if (DataReporterCollections.ContainsKey(uniqueKey)) {
                MessageBox.Show($@"数据集合唯一键不能重复：{uniqueKey}", @"重复提示");
                return;
            }
            string info = CollectionUtil.StringLimitJoin(selected.Select(each => each.Uniquekey).ToList(), 50);
            Console.WriteLine($@"创建数据采集集合:{uniqueKey}，共有{selected.Count}个成员：[{info}]");
            DataReporterCollection collection = DataReporterCollection.CreateByImplements(uniqueKey, selected);
            dataReporterCollections.Add(collection.Uniquekey, collection);
            dataReporterCollectionNames.Add(collection.Uniquekey);
            application.ResultHolder.RegisterStatistic(collection, ListenerGenerator.CreateListenerByReporter(collection));
            Refresh();
        }

        private void DeleteReporterCollectionButton_Click(object sender, EventArgs e) {
            var items = CreatedReporterCollectionListBox.SelectedItems.Cast<string>().ToList();
            foreach (var key in items) {
                Console.WriteLine($@"删除 DataReporterCollection: {key}]");
                dataReporterCollections.Remove(key);
                dataReporterCollectionNames.Remove(key);
                application.ResultHolder.RemoveStatistic(key);
            }
        }

        private void ReporterGroupComboBox_SelectedValueChanged(object sender, EventArgs e) {
            if (ReporterGroupComboBox.SelectedItem == null) {
                return;
            }
            var groupKey = ReporterGroupComboBox.SelectedItem.ToString();
            var reporters = ReporterGroup[groupKey];
            DataReporterBindingList = new DataReporterBindingList(groupKey, new List<DataReporter>(reporters), ReporterSelectView);
            currentShowingReporters = ReporterGroup[groupKey].ToDictionary(each => each.Uniquekey);
        }

        private void ClearSelectedButton_Click(object sender, EventArgs e) {
            Console.WriteLine($@"清空 DataReporterCollection");
            dataReporterCollections.Clear();
            dataReporterCollectionNames.Clear();
            application?.ResultHolder?.RemoveAllStatistic();
        }

        private void CreatedReporterCollectionListBox_SelectedValueChanged(object sender, EventArgs e) {
            string reporterUniqueKey = (string)CreatedReporterCollectionListBox.SelectedItem;
            if (reporterUniqueKey == null) {
                singleReporterVariableNames.Bind(null);
                return;
            }
            singleReporterVariableNames.Bind(dataReporterCollections[reporterUniqueKey]);
        }

    }
}
